package nu.zoom.swing.desktop.frame;

import java.awt.EventQueue;
import java.awt.Point;
import java.awt.event.ActionListener;

import javax.swing.JComponent;
import javax.swing.JDesktopPane;
import javax.swing.JInternalFrame;
import javax.swing.JMenuBar;
import javax.swing.KeyStroke;

import nu.zoom.swing.desktop.Workbench;
import nu.zoom.swing.desktop.WorkbenchFrame;
import nu.zoom.swing.desktop.WorkbenchKeybinding;
import nu.zoom.swing.desktop.WorkbenchMenuBar;
import nu.zoom.swing.desktop.preferences.Preferences;
import nu.zoom.swing.desktop.worker.WorkerFactory;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.ops4j.gaderian.Messages;

public class Desktop implements WorkbenchKeybinding {

	private Log log = LogFactory.getLog(getClass());
	private static final Point[] defaultOpenPoints = { new Point(5, 5), new Point(15, 15), new Point(25, 25),
			new Point(35, 35), new Point(45, 45) };
	private int currentDefaultPoint = 0;
	private final WorkbenchFrames workbenchFrames;
	private final Preferences preferences;
	private final Workbench workbench;
	private final JDesktopPane desktopPane;
	private final DesktopScrollbarManager desktopmanager;

	/**
	 * Must be called on the EventQueue
	 * 
	 * @param messages
	 * @param workbenchMenuBar
	 * @param preferences
	 * @param workbench
	 */
	public Desktop(final Messages messages, final WorkbenchMenuBar workbenchMenuBar, final Preferences preferences,
			Workbench workbench) {
		if (!EventQueue.isDispatchThread()) {
			throw new IllegalStateException("Not running on event queue");
		}
		this.preferences = preferences;
		this.workbench = workbench;
		workbenchFrames = new WorkbenchFrames(messages, workbenchMenuBar);
		desktopPane = new JDesktopPane();
		desktopmanager = new DesktopScrollbarManager(desktopPane);
	}

	public WorkbenchFrame createFrame(final String preferencesKey, final JComponent content, final JMenuBar menu,
			final boolean resizable, final boolean maximizable, final Boolean detachedOverride) {

		WorkbenchFrame frame =
				new DetachableWorkbenchFrame(content, menu, resizable, maximizable, workbenchFrames, preferences,
						preferencesKey, this, detachedOverride);

		return postCreate(frame);
	}

	private WorkbenchFrame postCreate(WorkbenchFrame frame) {
		// Add the real frame to the frames collection. The proxy will not work
		// since the Swing callbacks for frame closing does not go through the
		// proxy, thus the callback will reference the real frame and not the
		// proxy
		workbenchFrames.addFrame(frame);
		log.trace("Decorating workbench frame with an event queue worker proxy");
		WorkbenchFrame proxy = WorkerFactory.decorate(frame, WorkbenchFrame.class);

		return proxy;
	}

	public void closeAll() {
		workbenchFrames.closeAll();
	}

	public JComponent getDesktopPane() {
		return desktopmanager.getDesktopScroller();
	}

	synchronized Point getNextDefaultPosition() {
		currentDefaultPoint++;
		if (currentDefaultPoint >= defaultOpenPoints.length) {
			currentDefaultPoint = 0;
		}

		return defaultOpenPoints[currentDefaultPoint];
	}

	int getMaxWidth() {
		return workbench.getDialogOwner().getWidth();
	}

	int getMaxHeight() {
		return workbench.getDialogOwner().getHeight();
	}

	void addToDesktop(JInternalFrame frame) {
		desktopPane.add(frame);
	}

	@Override
	public void registerKeyboardAction(ActionListener anAction, KeyStroke aKeyStroke, int aCondition) {
		desktopPane.registerKeyboardAction(anAction, aKeyStroke, aCondition);
	}

	@Override
	public void registerKeyboardAction(ActionListener anAction, String aCommand, KeyStroke aKeyStroke, int aCondition) {
		desktopPane.registerKeyboardAction(anAction, aCommand, aKeyStroke, aCondition);
	}
}
